# -*- encoding: utf-8 -*-

# Copyright 2010 István Szentandrási
# <etude-music-player@googlegroups.com>

# This file is part of Etude.
#
# Etude is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as 
# published by the Free Software Foundation, either version 3 
# of the License, or (at your option) any later version.
#
# Etude is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Etude. If not, see <http://www.gnu.org/licenses/>.

from . import _
_b = __builtins__['_']

"""
Current song information plugin
"""

import etude.plugins as ep
import etude.client as ec
import etude.gui as eg
import etude.img as img
import gtk
import gobject
import pango

FORMAT = ("{[b]"+_b("title").capitalize()+":[/b] <title>\n}"+
        "{[b]"+_b("channel").capitalize()+":[/b] <channel>\n}"+
        "{[b]"+_b("artist").capitalize()+":[/b] <artist>\n}"+
        "{[b]"+_b("album").capitalize()+":[/b] <album>\n}"+
        "{[b]"+_b("duration").capitalize()+":[/b] <duration>\n}"+
        "{[b]"+_b("date").capitalize()+":[/b] <date>\n}"+
        "{[b]"+_b("track").capitalize()+":[/b] <tracknr>\n}"+
        "{[b]"+_b("genre").capitalize()+":[/b] <genre>\n}"+
        "{[b]"+_b("url").capitalize()+":[/b] <url>\n}"+
        "{[b]"+_b("bitrate").capitalize()+":[/b] <bitrate> kbps\n}"+
        "{[b]"+_b("comment").capitalize()+":[/b] <comment>\n}"+
        "{[b]"+_("last started").capitalize()+":[/b] <laststarted>\n}"+
        "{[b]"+_("times played").capitalize()+":[/b] <timesplayed>\n}")
ALBUMART_SIZE = 150
ALBUMART_BIG_SIZE = 300
COVER_SOURCE = 'client/generic/covers'
MAIN_PROP = 'picture_front'
EXTRA_PROP = 'picture_front_alternatives'



class SongInfo(ep.PluginPanel):

    _type = ep.E_PANEL_TYPE_INFO
    _short_name = "Songinfo"
    _show_name = _("Info")
    _short_descr = _("Details about the currently playing song.")
    _version = "0.1"
    _unique = "Default_Songinfo-0.1"
    _title = _("Info")
    _config = { }


    def __init__(self, control):
        ep.PluginPanel.__init__(self, control)
        self.client = control.client
        self.config = control.config
        self.set_shadow_type(gtk.SHADOW_NONE)
 
        self.scrolledw = gtk.ScrolledWindow()
        self.scrolledw.set_policy( gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        self.add(self.scrolledw)

        self.vbox = gtk.VBox()
        self.scrolledw.add_with_viewport(self.vbox)
        
        self.info_exp = gtk.Expander(label="<i><b>"+_("Song info")+"</b></i>")
        self.info_exp.set_use_markup(True)
        self.info_exp.set_expanded(True)
        self.vbox.pack_start(self.info_exp, False, False, 10)
        
        self.hbox = gtk.HBox()
        self.info_exp.add(self.hbox)

        info_vbox = gtk.VBox()
        self.info_label = gtk.Label()
        #self.info_label.set_ellipsize(pango.ELLIPSIZE_END)
        self.info_label.set_line_wrap(True)
        self.info_label.set_use_markup(True)
        align = gtk.Alignment(xalign = 0.0)
        align.add(self.info_label)
        info_vbox.pack_start(align, False, False)
        
        #edit info
        self.edit_info = gtk.EventBox()
        label = gtk.Label('<span foreground="blue">(%s)</span>' % _('edit'))
        label.set_use_markup(True)
        self.edit_info.add(label)
        align = gtk.Alignment(xalign = 0.0)
        align.add(self.edit_info)
        info_vbox.pack_start(align, False, False, 5)
        
        self.hbox.pack_start(info_vbox, True, True, 0)
        
        self.album_art = gtk.Image()
        self.album_art.set_size_request(ALBUMART_SIZE, ALBUMART_SIZE)
        eventbox = gtk.EventBox()
        eventbox.add(self.album_art)
        align = gtk.Alignment(yalign = 0.0)
        align.add(eventbox)
        self.hbox.pack_start(align, False, False, 0)
        eventbox.connect('button-press-event', self.on_album_art)


        self.lyrics_exp = gtk.Expander(label="<i><b>"+_("Lyrics")+"</b></i>")
        self.lyrics_exp.set_use_markup(True)
        self.lyrics_exp.set_expanded(True)
        self.vbox.pack_start(self.lyrics_exp, False, False, 0)

        lyrics_vbox = gtk.VBox()
        #custom lyrics
        self.custom_lyrics_label = gtk.EventBox()
        label = gtk.Label('<span foreground="blue">(%s)</span>' % _('find'))
        label.set_use_markup(True)
        self.custom_lyrics_label.add(label)
        #edit label
        self.edit_lyrics_label = gtk.EventBox()
        label = gtk.Label('<span foreground="blue">(%s)</span>' % _('edit'))
        label.set_use_markup(True)
        self.edit_lyrics_label.add(label)
        lyrics_hbox = gtk.HBox()
        lyrics_hbox.pack_start(self.custom_lyrics_label, False, False, 5)
        lyrics_hbox.pack_start(self.edit_lyrics_label, False, False, 5)
        lyrics_vbox.pack_start(lyrics_hbox, False, False)
        
        self.lyrics_label = gtk.Label()
        self.lyrics_label.set_line_wrap(True)
        align = gtk.Alignment(xalign = 0.0)
        align.add(self.lyrics_label)
        lyrics_vbox.pack_start(align, True, True)

        self.lyrics_exp.add(lyrics_vbox)

        self.show_all()

        self.custom_lyrics_label.hide()
        self.custom_lyrics_label.connect('button-press-event',
                self.custom_lyrics_dialog)
        self.edit_lyrics_label.connect('button-press-event',
                self.edit_lyrics_dialog)
        self.edit_info.connect('button-press-event', self.edit_info_dialog)
        self.bind(self.client, "e_playback_current_id", self.song_changed)
        self.bind(self.client, "e_medialib_entry_changed", self.entry_changed)
        self.bind(self.control, "g_interface_added", self.update_custom_lyrics)
        self.bind(self.control, "g_interface_removed",
                self.update_custom_lyrics)
        self.update_custom_lyrics(self.control, 'fetch_lyrics')
        for widg in (self.edit_info, self.edit_lyrics_label,
                self.custom_lyrics_label):
            widg.connect('enter-notify-event', self.__set_cursor)

    def edit_lyrics_dialog(self, widget, event, data = None):
        def add_cb(md5_hash):
            if md5_hash == None:
                return
            if minfo.has_key('lyrics') and len(minfo['lyrics']) != 0:
                self.client.bindata.remove(minfo['lyrics'])
            self.client.medialib.property_set(minfo['id'], 'lyrics',
                    md5_hash, source = 'client/generic')

        dialog = gtk.MessageDialog( self.get_toplevel(),
                gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                gtk.MESSAGE_OTHER,
                buttons=gtk.BUTTONS_OK_CANCEL
                )
        minfo = ec.MediaInfo(self.client.playback.current_info)
        dialog.set_markup(_("Edit lyrics for") + ": " + 
                minfo.get_custom_info('{<artist> - }<smart>')[0])
        dialog.set_title(_("Edit lyrics"))
        textbuf = gtk.TextBuffer()
        textbuf.insert(textbuf.get_start_iter(), self.lyrics_label.get_label())
        textview = gtk.TextView(textbuf)
        textview.set_editable(True)
        textview.set_size_request(300, 300)
        scroll = gtk.ScrolledWindow()
        scroll.set_shadow_type( gtk.SHADOW_ETCHED_IN)
        scroll.set_policy( gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        scroll.add(textview)
        dialog.vbox.pack_start(scroll)
        
        dialog.show_all()
        res = dialog.run()
        if res == gtk.RESPONSE_OK:
            text = str(textbuf.get_text(textbuf.get_start_iter(),
                textbuf.get_end_iter()).encode('utf-8'))
            self.client.bindata.add(text, add_cb)
        dialog.destroy()

    def edit_info_dialog(self, widget, event, data = None):
        dialog = eg.MediaInfoDialog(self.get_toplevel(), self.control, 
                self.client.playback.current_info)
        dialog.show_all()
        res = dialog.run()
        if res == gtk.RESPONSE_OK:
            dialog.save_info()
        dialog.destroy()

    def __set_cursor(self, widg, event = None):
        cursor = gtk.gdk.Cursor(gtk.gdk.HAND2)
        widg.get_window().set_cursor(cursor)

    def custom_lyrics_dialog(self, wigdet, event, data = None):
        dialog = gtk.MessageDialog( self.get_toplevel(),
                gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
                gtk.MESSAGE_OTHER,
                buttons=gtk.BUTTONS_OK_CANCEL
                )
        minfo = ec.MediaInfo(self.client.playback.current_info)
        dialog.set_default_size(300, 200)
        dialog.set_markup(_("Enter or change the artist and title:"))
        dialog.set_title(_("Find lyrics"))
        #inputfield
        entry = gtk.Entry()
        if minfo.has_key('artist'):
            entry.set_text(minfo['artist'])
        entry2 = gtk.Entry()
        if minfo.has_key('title'):
            entry2.set_text(minfo['title'])
        #allow using enter
        entry.connect('activate',
                lambda widget: dialog.response(gtk.RESPONSE_OK))
        entry2.connect('activate',
                lambda widget: dialog.response(gtk.RESPONSE_OK))
        
        table = gtk.Table(rows = 2, columns = 2)
        table.attach(gtk.Label(_b("artist").capitalize()+":"), 0, 1, 0, 1,
                xoptions = 0, yoptions = 0)
        table.attach(entry, 1, 2, 0, 1,
                xoptions = gtk.FILL|gtk.EXPAND, yoptions = 0)
        
        table.attach(gtk.Label(_b("title").capitalize()+":"), 0, 1, 1, 2,
                xoptions = 0, yoptions = 0)
        table.attach(entry2, 1, 2, 1, 2,
                xoptions = gtk.FILL|gtk.EXPAND, yoptions = 0)
        
        dialog.vbox.add(table)
        dialog.show_all()
        res = dialog.run()
        if res == gtk.RESPONSE_OK:
            artist = entry.get_text()
            title = entry2.get_text()
            if len(artist)>0 and len(title)>0:
                self.control.use_interface('fetch_lyrics',
                        (minfo['id'], artist, title))
        dialog.destroy()


    def update_custom_lyrics(self, control, name):
        if name != 'fetch_lyrics':
            return False
        if self.control.has_interface('fetch_lyrics'):
            self.custom_lyrics_label.show()
        else:
            self.custom_lyrics_label.hide()

    def on_album_art(self, widget, event, data=None):
        """show albumart chooser, if the album image was clicked"""
        if event.button == 1:
            nfo = self.client.playback.current_info
            if not nfo.has_key(MAIN_PROP):
                pic_hash = None
            else:
                pic_hash = nfo[MAIN_PROP]
            if max(*(self.album_art.get_size_request()))<=ALBUMART_SIZE:
                self.set_albumart(hash = pic_hash, size = ALBUMART_BIG_SIZE)
            else:
                self.set_albumart(hash = pic_hash)
        elif event.button == 3:
            nfo = self.client.playback.current_info
            #if nfo.has_key(MAIN_PROP) or nfo.has_key(EXTRA_PROP):
            self.show_alter_popup(widget, event, data)

    def show_alter_popup(self, widget, event, data):
        """show the popup menu after clicking the albumart"""
        time = event.time
        
        menu = gtk.Menu()
        item = gtk.MenuItem(label= _("Choose alternative"))
        item.connect('activate', self.alternative_chooser)
        menu.append(item)    
         
        menu.show_all()
        menu.popup(None, None, None, event.button, event.time)

    
    def alternative_chooser(self, widget, data = None):
        """show the alternative cover chooser dialog and change the 
        medialib properties if necessary"""
        nfo = self.client.playback.current_info
        dialog = eg.AlternativeImageChooser(self, self.control, nfo)
        t = dialog.run()
        if t == gtk.RESPONSE_OK:
            dialog.apply_selected() 
        dialog.destroy()


    def song_changed(self, widget, song_id):
        """if the song changed, change the info too"""
        nfo = self.client.playback.current_info
        row = nfo.get_custom_info(FORMAT)[0]
        self.info_label.set_markup(row)
        if nfo.has_key(MAIN_PROP):
            self.set_albumart(hash = nfo[MAIN_PROP])
        else:
            self.set_albumart()
        #we should check a cache of lyrics
        if nfo.has_key('lyrics'):
            self.set_lyrics(hash = nfo['lyrics'])
        else:
            self.set_lyrics()
        return False
        
    def set_albumart(self, pixbuf = None, hash = None, size = ALBUMART_SIZE):
        """get the albumart image from the daemon"""
        def _bindata_cb(value):
            pb = img.get_pixbuf_from_data(value)
            self.set_albumart(pixbuf = pb, size = size)
        if hash != None:
            self.client.bindata.retrieve(hash, _bindata_cb)
            return
        elif pixbuf == None:
            pixbuf = gtk.icon_theme_get_default().load_icon('etude', size, 0)
        pixbuf, w, h = img.get_pixbuf_of_size(pixbuf, size)
        self.album_art.set_from_pixbuf(pixbuf)
        self.album_art.set_size_request(w, h)
        self.hbox.resize_children()

    def entry_changed(self, widget, song_id):
        """if the current song changed update the info"""
        pb = self.client.playback
        try:
            if pb.current_info['id'] == song_id:
                self.song_changed(widget, song_id)
        except KeyError:
            pass

    def set_lyrics(self, text = None, hash = None):
        """set the lyrics"""
        def _bindata_cb(value):
            self.set_lyrics(text = value)
        if hash != None:
            self.client.bindata.retrieve(hash, _bindata_cb)
            return
        elif text != None:
            try:
                pango.parse_markup(text)
            except gobject.GError:
                self.lyrics_label.set_text(text)
            else:
                self.lyrics_label.set_markup(text)
        else:
            self.lyrics_label.set_markup('')
        return False

